#ifndef _SOCKETS_H_
#define _SOCKETS_H_

#include "dev.h"
#include "queue.h"
#include "emac_params.h"
#include "user_timers.h"
#include "err.h"

#define ntohl(value)  htonl(value)
#define ntohs(value)  htons(value)

typedef enum
{
    SOCK_OPT_IPC_HANDLER,
    SOCK_OPT_MAX
}sock_opt_type;


typedef struct
{
    dev_handle_t dev_handle;

    /*
    * Pointer to shared memory 
    * containing device params like
    * mac-addr, ip-addr etc.
    */
    emac_params_t *emac_params;
    void          *shmem_handle;

    /*
    * registering a handler to recieve normal IPC 
    * messages on the socket queue
    */
    void  (*ipc_msg_handler)(uint8_t *data, uint16_t len);

    queue_handle_t queue_handle;  // handle to socket queue
}socket_t;

typedef struct
{
    uint32_t ip_addr;
    uint16_t port;
    uint8_t  *data;
    uint16_t len;
}socket_data_t;

typedef struct
{
    uint8_t dst_mac[6];
    uint8_t src_mac[6];
    uint16_t l3_protocol;  // ip
    uint8_t hlen:4;  // header len
    uint8_t version:4; 
    uint8_t extra;  // type of service
    uint16_t total_len; // hdr + payload
    uint16_t ident;
    uint16_t frag_flags;
    uint8_t ttl;
    uint8_t l4_proto;
    uint16_t hdr_csum;
    uint32_t source_ip;
    uint32_t dest_ip;
    uint8_t data[0];
}__attribute__((__packed__)) ip_hdr_t;

typedef struct
{
    ip_hdr_t ip_hdr;
    uint16_t src_port;
    uint16_t dst_port;
    uint16_t udp_len;
    uint16_t checksum;
    uint8_t data[0];
}__attribute__((__packed__))udp_hdr_t;



uint16_t htons(uint16_t value);
uint32_t htonl(uint32_t value);

err_t open_udp_socket(uint8_t *name, uint16_t port_no, void **sock_handle);
err_t open_ip_socket(uint8_t *name, uint16_t port_no, void **sock_handle);
err_t set_sock_opt(void *handle, sock_opt_type sock_opt, uint32_t value);
err_t close_socket(void *sock);
err_t send_on_socket(void *sock, socket_data_t *sock_data);
err_t rcv_socket(void *handle, socket_data_t *sock_data, uint8_t *buffer, uint16_t *len);
err_t socket_timer_start(void *handle, user_timer_data_t *timer_data);
uint16_t calc_ip_checksum(uint16_t *data, uint8_t words);
err_t socket_close(void *handle);

#endif
